<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Blockly Generator Tests</title>
<script src="../../blockly_uncompressed.js"></script>

<script src="../../generators/javascript.js"></script>
<script src="unittest_javascript.js"></script>
<script src="../../generators/javascript/logic.js"></script>
<script src="../../generators/javascript/loops.js"></script>
<script src="../../generators/javascript/math.js"></script>
<script src="../../generators/javascript/text.js"></script>
<script src="../../generators/javascript/lists.js"></script>
<script src="../../generators/javascript/colour.js"></script>
<script src="../../generators/javascript/variables.js"></script>
<script src="../../generators/javascript/procedures.js"></script>

<script src="../../generators/python.js"></script>
<script src="unittest_python.js"></script>
<script src="../../generators/python/logic.js"></script>
<script src="../../generators/python/loops.js"></script>
<script src="../../generators/python/math.js"></script>
<script src="../../generators/python/text.js"></script>
<script src="../../generators/python/lists.js"></script>
<script src="../../generators/python/colour.js"></script>
<script src="../../generators/python/variables.js"></script>
<script src="../../generators/python/procedures.js"></script>

<script src="../../generators/php.js"></script>
<script src="unittest_php.js"></script>
<script src="../../generators/php/logic.js"></script>
<script src="../../generators/php/loops.js"></script>
<script src="../../generators/php/math.js"></script>
<script src="../../generators/php/text.js"></script>
<script src="../../generators/php/lists.js"></script>
<script src="../../generators/php/colour.js"></script>
<script src="../../generators/php/variables.js"></script>
<script src="../../generators/php/procedures.js"></script>

<script src="../../generators/lua.js"></script>
<script src="unittest_lua.js"></script>
<script src="../../generators/lua/logic.js"></script>
<script src="../../generators/lua/loops.js"></script>
<script src="../../generators/lua/math.js"></script>
<script src="../../generators/lua/text.js"></script>
<script src="../../generators/lua/lists.js"></script>
<script src="../../generators/lua/colour.js"></script>
<script src="../../generators/lua/variables.js"></script>
<script src="../../generators/lua/procedures.js"></script>

<script src="../../generators/dart.js"></script>
<script src="unittest_dart.js"></script>
<script src="../../generators/dart/logic.js"></script>
<script src="../../generators/dart/loops.js"></script>
<script src="../../generators/dart/math.js"></script>
<script src="../../generators/dart/text.js"></script>
<script src="../../generators/dart/lists.js"></script>
<script src="../../generators/dart/colour.js"></script>
<script src="../../generators/dart/variables.js"></script>
<script src="../../generators/dart/procedures.js"></script>

<script src="unittest.js"></script>
<script src="../../msg/messages.js"></script>
<script src="../../blocks/logic.js"></script>
<script src="../../blocks/loops.js"></script>
<script src="../../blocks/math.js"></script>
<script src="../../blocks/text.js"></script>
<script src="../../blocks/lists.js"></script>
<script src="../../blocks/colour.js"></script>
<script src="../../blocks/variables.js"></script>
<script src="../../blocks/procedures.js"></script>

<script>
'use strict';

var demoWorkspace = null;
var outputCode = '';

function start() {
  demoWorkspace = Blockly.inject('blocklyDiv',
      {grid:
         {spacing: 25,
          length: 3,
          colour: '#ccc',
          snap: true},
       media: '../../media/',
       toolbox: document.getElementById('toolbox'),
       zoom: {controls: true, wheel: true}
       });
  changeIndex();
}

/**
 * Run this test to load all of the tests in the selected suites.  The contents
 * will be loaded into the workspace in order.  To test the generators:
 * - select your language from the buttons above the text area
 * - copy all of the generated code
 * - run it in an interpreter of your choice
 * - scan all of the results for "FAIL".  All test suites are running in order,
 *      and each will report OK or FAIL based only on the tests in that suite.
 * If some tests are failing, load test suites individually to continue
 * debugging.
 */
function loadSelected() {
  var output = document.getElementById('importExport');
  output.style.background = 'gray';

  var loadingElem = document.getElementById('loading');
  loadingElem.textContent = 'loading...';

  // Clear before adding all of the blocks.
  demoWorkspace.clear();

  var boxList = document.getElementsByClassName('suite_checkbox');
  for (var i = 0; i < boxList.length; i++) {
    if (boxList[i].checked) {
      var testUrl = boxList[i].value;
      if (testUrl) {
        var xmlText = fetchFile(testUrl);
        if (xmlText !== null) {
          fromXml(testUrl, xmlText, /* opt_append */ true);
        }
      }
    }
  }
  output.style.background = '';
  loadingElem.textContent = 'done';
}

/**
 * Ask the user for a file name, then load that file's contents.
 */
function loadOther() {
  var url = window.prompt('Enter URL of test file.');
  if (!url) {
    return;
  }
  var xmlText = fetchFile(url);
  if (xmlText !== null) {
    fromXml(url, xmlText);
  }
}

function fetchFile(xmlUrl) {
  try {
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open('GET', xmlUrl, false);
    xmlHttp.setRequestHeader('Content-Type', 'text/xml');
    xmlHttp.send('');
  } catch (e) {
    // Attempt to diagnose the problem.
    var msg = 'Error: Unable to load XML data.\n';
    if (window.location.protocol == 'file:') {
      msg += 'This may be due to a security restriction preventing\n' +
          'access when using the file:// protocol.\n' +
          'Use an http webserver, or a less paranoid browser.\n';
    }
    alert(msg + '\n' + e);
    return null;
  }
  return xmlHttp.responseText;
}

/**
 * @param {string} filename The URL (or other name) of the XML, for reporting.
 * @param {string} xmlText The actual XML text.
 * @param {boolean=} opt_append True if the XML should be appended to the
 *     workspace.  Otherwise the workspace is cleared and the new XML is loaded.
 */
function fromXml(filename, xmlText, opt_append) {
  var output = document.getElementById('importExport');
  output.value = xmlText;
  output.scrollTop = 0;
  output.scrollLeft = 0;
  if (!opt_append) {
    demoWorkspace.clear();
  }
  try {
    var xmlDoc = Blockly.Xml.textToDom(xmlText);
    if (opt_append) {
      Blockly.Xml.appendDomToWorkspace(xmlDoc, demoWorkspace);
    } else {
      Blockly.Xml.domToWorkspace(xmlDoc, demoWorkspace);
    }
  } catch (e) {
    var msg = 'Error parsing XML: ' + filename + '\n\n\t' + e;
    if (e.stack) {
      msg += '\n\nSee console for stack trace details.'
    }
    console.error(e.stack ? e : msg);
    alert(msg);
    return;
  }
}

function checkAll() {
  var boxList = document.getElementsByClassName('suite_checkbox');
  for (var i = 0; i < boxList.length; i++) {
    boxList[i].checked = true;
  }
}

function uncheckAll() {
  var boxList = document.getElementsByClassName('suite_checkbox');
  for (var i = 0; i < boxList.length; i++) {
    boxList[i].checked = false;
  }
}

function setOutput(text) {
  var output = document.getElementById('importExport');
  output.value = text;
  output.focus();
  output.select();
}

function toXml() {
  var xmlDom = Blockly.Xml.workspaceToDom(demoWorkspace,
    /* opt_noId */ true);
  var xmlText = Blockly.Xml.domToPrettyText(xmlDom);
  xmlText = xmlText.replace(/ id="\d+"/g, '');
  setOutput(xmlText);
}

function toJavaScript() {
  var code = '\'use strict\';\n\n'
  code += Blockly.JavaScript.workspaceToCode(demoWorkspace);
  setOutput(code);
  outputCode = code;
}

function toPython() {
  var code = Blockly.Python.workspaceToCode(demoWorkspace);
  setOutput(code);
  outputCode = code;
}

function toPhp() {
  var code = Blockly.PHP.workspaceToCode(demoWorkspace);
  setOutput(code);
  outputCode = code;
}

function toLua() {
  var code = Blockly.Lua.workspaceToCode(demoWorkspace);
  setOutput(code);
  outputCode = code;
}

function toDart() {
  var code = Blockly.Dart.workspaceToCode(demoWorkspace);
  setOutput(code);
  outputCode = code;
}

function changeIndex() {
  var oneBasedIndex = document.getElementById('indexing').checked;
  demoWorkspace.options.oneBasedIndex = oneBasedIndex;
  demoWorkspace.getToolbox().flyout_.workspace_.options.oneBasedIndex = oneBasedIndex;
}
</script>

<style>
html, body {
  height: 100%;
  overflow: hidden;
}
body {
  background-color: #fff;
  font-family: sans-serif;
  margin: 0 5px;
}
h1 {
  font-weight: normal;
  font-size: 140%;
}
#blocklyDiv {
  float: right;
  height: 95%;
  width: 69%;
  margin-top: 5px;
}
#importExport {
  height: 100%;
  width: 100%;
}
#loading {
  color: red;
}
</style>
</head>
<body onload="start()">

  <div id="blocklyDiv"></div>

  <xml xmlns="https://developers.google.com/blockly/xml" id="toolbox" style="display: none">
    <category name="Unit test" colour="65">
      <block type="unittest_main"></block>
      <block type="unittest_assertequals">
        <value name="MESSAGE">
          <block type="text">
            <field name="TEXT"></field>
          </block>
        </value>
      </block>
      <block type="unittest_assertvalue">
        <value name="MESSAGE">
          <block type="text">
            <field name="TEXT"></field>
          </block>
        </value>
      </block>
      <block type="unittest_fail"></block>
      <block type="unittest_adjustindex"></block>
    </category>
    <category name="Logic" colour="210">
      <block type="controls_if"></block>
      <block type="controls_ifelse"></block>
      <block type="logic_compare"></block>
      <block type="logic_operation"></block>
      <block type="logic_negate"></block>
      <block type="logic_boolean"></block>
      <block type="logic_null"></block>
      <block type="logic_ternary"></block>
    </category>
    <category name="Loops" colour="120">
      <block type="controls_repeat_ext"></block>
      <block type="controls_whileUntil"></block>
      <block type="controls_for"></block>
      <block type="controls_forEach"></block>
      <block type="controls_flow_statements"></block>
    </category>
    <category name="Math" colour="230">
      <block type="math_number"></block>
      <block type="math_arithmetic"></block>
      <block type="math_single"></block>
      <block type="math_trig"></block>
      <block type="math_constant"></block>
      <block type="math_number_property"></block>
      <block type="math_round"></block>
      <block type="math_on_list"></block>
      <block type="math_modulo"></block>
      <block type="math_constrain"></block>
      <block type="math_random_int"></block>
      <block type="math_random_float"></block>
      <block type="math_atan2"></block>
    </category>
    <category name="Text" colour="160">
      <block type="text"></block>
      <block type="text_join"></block>
      <block type="text_append"></block>
      <block type="text_length"></block>
      <block type="text_isEmpty"></block>
      <block type="text_indexOf"></block>
      <block type="text_charAt"></block>
      <block type="text_getSubstring"></block>
      <block type="text_changeCase"></block>
      <block type="text_trim"></block>
      <block type="text_print"></block>
      <block type="text_prompt_ext"></block>
      <block type="text_count"></block>
      <block type="text_replace"></block>
      <block type="text_reverse"></block>
      <block type="text_multiline"></block>
    </category>
    <category name="Lists" colour="260">
      <block type="lists_create_empty"></block>
      <block type="lists_create_with"></block>
      <block type="lists_repeat"></block>
      <block type="lists_length"></block>
      <block type="lists_isEmpty"></block>
      <block type="lists_indexOf"></block>
      <block type="lists_getIndex"></block>
      <block type="lists_setIndex"></block>
      <block type="lists_getSublist"></block>
      <block type="lists_sort"></block>
      <block type="lists_split"></block>
      <block type="lists_reverse"></block>
    </category>
    <category name="Colour" colour="20">
      <block type="colour_picker"></block>
      <block type="colour_random"></block>
      <block type="colour_rgb"></block>
      <block type="colour_blend"></block>
    </category>
    <sep></sep>
    <category name="Variables" colour="330" custom="VARIABLE"></category>
    <category name="Functions" colour="290" custom="PROCEDURE"></category>
  </xml>

  <table height="95%" width="30%"><tr><td valign="top">
    <h1>Blockly Generator Tests</h1>

    <p><a href="https://developers.google.com/blockly/guides/modify/web/unit-testing">See the docs</a> for details on running the tests.


    <div id="checkboxes">
      <input type="button" value="Check all" onclick="checkAll()">
      <input type="button" value="Uncheck all" onclick="uncheckAll()"><br/>
      <input type="checkbox" class="suite_checkbox" value="logic.xml">Logic</input><br/>
      <input type="checkbox" class="suite_checkbox" value="loops1.xml">Loops 1 (repeat, while, foreach)</input><br/>
      <input type="checkbox" class="suite_checkbox" value="loops2.xml">Loops 2 (count)</input><br/>
      <input type="checkbox" class="suite_checkbox" value="loops3.xml">Loops 3 (continue, break)</input><br/>
      <input type="checkbox" class="suite_checkbox" value="math.xml">Math</input><br/>
      <input type="checkbox" class="suite_checkbox" value="text.xml">Text</input><br/>
      <input type="checkbox" class="suite_checkbox" value="lists.xml">Lists</input><br/>
      <input type="checkbox" class="suite_checkbox" value="colour.xml">Colour</input><br/>
      <input type="checkbox" class="suite_checkbox" value="variables.xml">Variables</input><br/>
      <input type="checkbox" class="suite_checkbox" value="functions.xml">Functions</input><br/>
    </div>

    <p>
      <input type="button" value="Load selected" id="loadSelectedBtn" onclick="loadSelected()">
      <label for="loadSelectedBtn" id="loading"></label>
    </p>
    <p>
      <input type="button" value="Load by file name" onclick="loadOther()">
    </p>

    <p>
      <input id="indexing" type="checkbox" onchange="changeIndex()" checked>
      <label for="indexing">Generate with one-based indexing</label>
    </p>

    <p>
      Generate:
      <input type="button" value="XML" onclick="toXml()">
      <div style="display: inline-block;">
        <input type="button" value="JavaScript" onclick="toJavaScript()">
        <br><a target="_blank" href="https://repl.it/languages/javascript">interpreter</a>
      </div>
      <div style="display: inline-block;">
        <input type="button" value="Python" onclick="toPython()">
        <br><a target="_blank" href="https://repl.it/languages/python">interpreter</a>
      </div>
      <div style="display: inline-block;">
        <input type="button" value="PHP" onclick="toPhp()">
        <br><a target="_blank" href="https://repl.it/languages/php">interpreter</a>
      </div>
      <div style="display: inline-block;">
        <input type="button" value="Lua" onclick="toLua()">
        <br><a target="_blank" href="http://rextester.com/l/lua_online_compiler">interpreter</a>
      </div>
      <div style="display: inline-block;">
        <input type="button" value="Dart" onclick="toDart()">
        <br><a target="_blank" href="https://dartpad.dartlang.org/">interpreter</a>
      </div>
    </p>
  </td></tr><tr><td height="99%">
    <textarea id="importExport" readonly="readonly" wrap="off"></textarea>
  </td></tr></table>
</body>
</html>
